import { EnumSchema } from '@/utils/common/types';
import { List } from '@/components/Linqts';
import { ListNode } from './types';
import { FilterOperateEnum, FilterOperateEntity } from '@/enums/filterOperateEnum';
import { isFunction } from '@/utils/is';

//#region URL编码
/**
 * URL编码
 * @param url 待编码的URL
 */
export function urlEncode(url: string): string {
  return encodeURIComponent(url);
}
//#endregion
//#region URL解码
/**
 * URL解码
 * @param url 待解码的URL
 */
export function urlDecode(url: string): string {
  return decodeURIComponent(url);
}
//#endregion
//#region Base64字符串解码
/**
 * Base64字符串解码
 * @param base64 待编码的字符串
 */
export function fromBase64(base64: string): string {
  //return Buffer.from(base64, 'base64').toString();
  return window.atob(base64);
}
//#endregion
//#region Base64字符串编码
/**
 * Base64字符串编码
 * @param str 待解码的Base64字符串
 */
export function toBase64(str: string): string {
  //return Buffer.from(str).toString('base64');
  return window.btoa(str);
}
//#endregion

//#region 获取URL中Hash串中的查询参数值
/**
 * 获取URL中Hash串中的查询参数值
 * @param url URL字符串
 * @param name 参数名
 */
export function getHashURLSearchParams(url: string, name: string): string | null {
  if (url.indexOf('#') >= 0) {
    url = subStr(url, '#');
  }
  if (url.indexOf('?') >= 0) {
    url = subStr(url, '?');
  }
  const params = new URLSearchParams(url);
  return params.get(name);
}
//#endregion
//#region 提供首尾字符串截取中间的字符串
/**
 * 提供首尾字符串截取中间的字符串
 * @param str 待截取的字符串
 * @param start 起始的字符串
 * @param end 结束的字符串
 */
export function subStr(
  str: string,
  start: string | null = null,
  end: string | null = null,
): string {
  let startIndex = 0;
  let endIndex = str.length;
  if (start) {
    startIndex = str.indexOf(start) + start.length;
  }
  if (end) {
    endIndex = str.indexOf(end);
  }
  // return str.substr(startIndex, endIndex - startIndex);
  return str.substring(startIndex, endIndex);
}
//#endregion
//#region 从集合中删除符合条件的项
/**
 * 从集合中删除符合条件的项
 * @param items 集合
 * @param exp 删除项查询表达式
 */
export function remove<T>(items: Array<T>, exp: (value: T, index: number, obj: T[]) => boolean) {
  const index = items.findIndex(exp);
  items.splice(index, 1);
  return items;
}
//#endregion
//#region 值转文字
/**
 * 值转文字
 * @param id 待转换的值
 * @param array 数据节点集合
 * @param defaultText 转换失败时的默认文字
 */
export function valueToText(
  id: number,
  array: { id: number; text: string }[] | ListNode[],
  defaultText: string | null = null,
) {
  let text = defaultText == null ? id.toString() : defaultText;
  array.forEach((item) => {
    if (item.id === id) {
      text = item.text;
      return false;
    }
    return true;
  });
  return text;
}
//#endregion
//#region 展开集合拼接字符串
/**
 * 展开集合拼接字符串
 * @param array 待展开的集合
 * @param separator 分隔符
 */
export function expandAndToString(array: Array<any>, separator = ',') {
  let result = '';
  if (!array || !array.length) {
    return result;
  }
  array.forEach((item) => {
    result = result + item.toString() + separator;
  });
  return result.substring(0, result.length - separator.length);
}
//#endregion
//#region 下载数据
/**
 * 下载数据
 * @param filename 存储的文件名
 * @param content 下载得到的内容
 */
export function download(filename: string, content: string) {
  const blob = new Blob([content]);
  const urlLink = window.URL.createObjectURL(blob);

  const saveLink = document.createElement('a');
  saveLink.style.display = 'none';
  saveLink.href = urlLink;
  saveLink.setAttribute('download', filename); //指定下载后的文件名，防跳转
  document.body.appendChild(saveLink);
  saveLink.click();

  //释放内存
  window.URL.revokeObjectURL(saveLink.href);
}
//#endregion

//#region 打开Email的网站
/**
 * 打开Email的网站
 * @param email Email地址
 */
export function openMailSite(email: string) {
  const host = subStr(email, '@');
  const url = `http://mail.${host}`;
  // console.log('openMailSite', { email, host, url });
  window.open(url);
}
//#endregion

//#region 获取文件扩展名
/**
 * 获取文件扩展名
 * @param filename 文件名称
 * @param includeSeparator 是否包含后缀名前置分隔符，默认true
 */
export function getFileExtname(filename: string, includeSeparator = true) {
  const separator = '.';
  // // 方法1 PS：不好用
  // const patternFileExtension = /\.([0-9a-z]+)(?:[\?#]|$)/i;
  // const fileExtname = filename.match(patternFileExtension);
  // return fileExtname?.toString() || '';

  // // 方法2
  // const result = filename.split(separator);
  // return result[result.length - 1];

  // 方法3
  let fileExtension = filename.split(separator).pop();
  fileExtension = fileExtension || '';
  if (fileExtension && includeSeparator) {
    return `${separator}${fileExtension}` || '';
  }
  return fileExtension || '';
}
//#endregion
//#region 去除文件扩展名
/**
 * 去除文件扩展名
 * @param filename 文件名称
 */
export function removeFileExtname(filename: string) {
  const fileExtension = getFileExtname(filename, true);
  const fileNameWithoutExtension = filename.replace(`${fileExtension}`, '');
  return fileNameWithoutExtension || '';
}
//#endregion
//#region 获取文件的Base64格式
/**
 * 获取文件的Base64格式
 * @param file 文件的信息
 * @param callback 转换成Base64后的回调
 */
export function getBase64(file: File, callback: (base64String: string) => void) {
  const reader = new FileReader();
  reader.addEventListener('load', () => callback(reader.result as string));
  reader.readAsDataURL(file);
}
//#endregion
//#region 获取文件的Base64格式
/**
 * 获取文件的Base64格式
 * @param file 文件的信息
 */
export function getBase64WithFile(file: File) {
  return new Promise<{
    result: string;
    file: File;
  }>((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve({ result: reader.result as string, file });
    reader.onerror = (error) => reject(error);
  });
}
//#endregion

//#region 获取Base64格式的文件对象
/**
 * 获取Base64格式的文件对象
 * @param base64Data Base64数据
 * @param fileName 文件名称
 */
export function getFileWithBase64(base64Data: string, fileName: string) {
  const arr = base64Data.split(',');
  if (arr && arr[0] && arr[1]) {
    const arr0match = arr[0].match(/:(.*?);/);
    let mime = '';
    if (arr0match) {
      mime = arr0match[1];
    }
    // const bytes = atob(arr[1]); // 解码base64
    const bytes = Buffer.from(arr[1], 'base64').toString(); // 解码base64
    let n = bytes.length;
    const ia = new Uint8Array(n);
    while (n--) {
      ia[n] = bytes.charCodeAt(n);
    }
    return new File([ia], fileName, { type: mime });
  }
  return null;
}
//#endregion

//#region 获取筛选操作实体集合
/**
 * 获取筛选操作实体集合
 * @param operates 筛选操作枚举集合
 * @returns 筛选操作实体集合
 */
export function getOperateEntities(operates: FilterOperateEnum[]): FilterOperateEntity[] {
  return new List(operates).Select((m: FilterOperateEnum) => new FilterOperateEntity(m)).ToArray();
}
//#endregion

//#region 根据远程方法转换枚举架构集合
/**
 * 根据远程方法转换枚举架构集合
 * @param apiFunction 远程方法
 * @param labelName 描述字段
 * @param valueName 值字段
 * @returns 枚举架构集合
 */
export async function readNode(
  apiFunction: () => Promise<any[]>,
  labelName: string,
  valueName: string,
): Promise<EnumSchema[]> {
  const enumSchema: EnumSchema[] = [];
  if (apiFunction && isFunction(apiFunction)) {
    const nodes = await apiFunction();
    if (nodes && nodes.length > 0) {
      nodes.forEach((item) => {
        enumSchema.push({
          key: item[valueName],
          label: item[labelName],
          value: item[valueName],
        });
      });
    }
  }
  return enumSchema;
}
//#endregion
